package facade;

import java.math.BigDecimal;
import java.util.*;

import usuarios.*;
import aerolineas.Aerolinea;
import aerolineas.AsientoNoDisponibleException;
import aerolineas.LanchitaAdapter;
import asientos.Asiento;
import busquedas.CriteriosBusqueda;

/* Este es el punto de entrada al sistema, es un facade singleton. */
public class AterrizarPuntoCom {
	private static final AterrizarPuntoCom INSTANCE = new AterrizarPuntoCom();
	
	private List<Aerolinea> aerolineas=new ArrayList<Aerolinea>();
	
	private AdministradorDePerfiles administradorDeUsuarios = new AdministradorDePerfiles();
	
	private static int recargo = 20;
	
	/* *************
	 * CONSTRUCCI�N
	 * ***********/
	
	/* El constructor es privado */
	private AterrizarPuntoCom() {
		// Agregamos las aerolineas.
		this.aerolineas.add(new LanchitaAdapter());
	}
	
	// Esta es la forma est�ndar de pedir instancias
	public static AterrizarPuntoCom getInstance() {
		return INSTANCE;
	}
	
	// Pero confiamos en el cliente y proveemos en al API otra forma, que devuelve una instancia nueva (no singleton), s�lo para testing.
	public static AterrizarPuntoCom nuevaInstanciaUsarSoloParaTesting() {
		return new AterrizarPuntoCom();
	}
	
	public List<Asiento> unUsuarioBuscaPasajes(CriteriosBusqueda criterios, Usuario unUsuario) {
		List<Asiento> asientos = new ArrayList<Asiento>();
		
		// busco asientos en todas mis aerolineas. 
		for(Aerolinea unaAerolina : this.aerolineas) {
			asientos.addAll(unaAerolina.asientosDisponibles(criterios));
		}
		
		List<Asiento> asientosFiltrados=this.filtrarAsientos(asientos, unUsuario);
		
		// guardo la busqueda al final, recien cuando se que anduvo todo bien
		// el administrador de usuarios, crea al perfil en la primer b�squeda
		// en el futuro, se supone que los usuarios estar�n pre creados, levantados de una base de datos o alg�n otro lado
		administradorDeUsuarios.GuardarBusqueda(unUsuario, criterios);
		
		return this.asientosConRecargo(asientosFiltrados, unUsuario, recargo);
	}

	private List<Asiento> asientosConRecargo(List<Asiento> asientos,
			Usuario unUsuario, int unRecargo) {
		for(Asiento unAsiento : asientos) {
			unAsiento.recargarSegunUsuario(unUsuario, unRecargo);
		}
		return asientos;
	}

	private List<Asiento> filtrarAsientos(List<Asiento> asientos,
			Usuario unUsuario) {
		List<Asiento> asientosFiltrados = new ArrayList<Asiento>();
		
		for(Asiento unAsiento : asientos) {
			if(unUsuario.debeVer(unAsiento)) {
				asientosFiltrados.add(unAsiento);
			}
		}
		
		return asientosFiltrados;
	}

	public AterrizarPuntoCom unUsuarioCompraUnAsiento(Usuario unUsuario, Asiento unAsiento){
		// Ac� podemos en un futuro hacer alguna otra cosa con el usuario.
	    for(Aerolinea unaAerolinea : this.aerolineas) {
	    	try {
	    		unaAerolinea.comprarAsiento(unAsiento.getCodigo());
	    		return this;
	    	}
	    	catch(AsientoNoDisponibleException e) {
	    		// No hacemos nada, seguimos buscando comprar el pasaje.
	    	}
	    }
	    
	    // No se pudo comprar el pasaje, lanzamos una excepci�n.
	    throw new AsientoNoDisponibleException(unAsiento.getCodigo());
	}
}